package gu.simplemq.redis;

import java.lang.reflect.Type;
import static com.google.common.base.Preconditions.*;
import static gu.simplemq.redis.RedisMQInstanceSupplier.MQ_INSTANCE_SUPPLIER;

import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;

import gu.simplemq.Channel;
import gu.simplemq.Constant;

/**
 * redis对象工厂类用于获取producer/consumer,publisher/subscriber,table对象<br>
 * 应用程序结束时会自动清除所有subscriber和consumer
 * @author guyadong
 *
 */
public class RedisFactory implements Constant {

	private RedisFactory() {}
	@SuppressWarnings("rawtypes")
	private static final Table<JedisPoolLazy,String,RedisTable> TABLE = HashBasedTable.create();
	public static<V> RedisTable<V> getTable(Class<V> clazz){
		return getTable((Type)clazz,
				JedisPoolLazys.NAMED_POOLS.getDefaultPool(),
				checkNotNull(clazz,"clazz is null").getSimpleName());
	}
	public static<V> RedisTable<V> getTable(Class<V> clazz,JedisPoolLazy pool, String tablename){
		return getTable((Type)clazz,pool,tablename);
	}
	public static<V> RedisTable<V> getTable(Channel<V> channel,JedisPoolLazy pool){
		return getTable(channel.type,pool,channel.name);
	}	
	/**
	 * 返回 {@link JedisPoolLazy}对应的{@link RedisTable}实例,如果{@link #TABLE}没有找到，
	 * 就创建一个新实例并加入{@link #TABLE}
	 * @param type
	 * @param pool
	 * @param tablename
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static <V> RedisTable<V> getTable(Type type,JedisPoolLazy pool, String tablename){
		checkArgument(null != type && null != pool && null != tablename,"input aruments must not be null");
		// Double Checked Locking
		if(!TABLE.contains(pool, tablename) ){
			synchronized(TABLE){
				if(!TABLE.contains(pool, tablename) ){
					@SuppressWarnings("unused")
					RedisTable previous = TABLE.put(pool, tablename, new RedisTable(type,pool,tablename));
				}
			}
		}
		RedisTable table = TABLE.get(pool,tablename);
		checkState(table.getType().equals(type),"mismatch type " + type + " vs " + table.getType());
		return table;
	}
	
	/**
	 * 返回 {@link JedisPoolLazy}对应的{@link RedisConsumer}实例
	 * @param jedisPoolLazy
	 */
	public static RedisConsumer getConsumer(JedisPoolLazy jedisPoolLazy) {
		return MQ_INSTANCE_SUPPLIER.getConsumer(jedisPoolLazy);
	}
	
	/**
	 * 返回 {@link JedisPoolLazy}对应的{@link RedisSubscriber}实例
	 * @param jedisPoolLazy
	 */
	public static RedisSubscriber getSubscriber(JedisPoolLazy jedisPoolLazy) {
		return MQ_INSTANCE_SUPPLIER.getSubscriber(jedisPoolLazy);
	}
	/**
	 * 返回 {@link JedisPoolLazy}对应的{@link RedisProducer}实例
	 * @param jedisPoolLazy
	 */
	public static RedisProducer getProducer(JedisPoolLazy jedisPoolLazy) {
		return MQ_INSTANCE_SUPPLIER.getProducer(jedisPoolLazy);
	}
	/**
	 * 返回 {@link JedisPoolLazy}对应的{@link RedisPublisher}实例
	 * @param jedisPoolLazy
	 */
	public static RedisPublisher getPublisher(JedisPoolLazy jedisPoolLazy) {
		return MQ_INSTANCE_SUPPLIER.getPublisher(jedisPoolLazy);
	}
}
